package com.tdk.common.util

import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume

object PermissionUtil {

    private const val TAG = "PermissionUtil"

    /**
     * Check if the permission is not granted
     * @param activity: ComponentActivity - Activity
     * @param permissionArray: Array<String> - Array of permissions
     * @return Pair<Array<String>, Boolean> - Pair of not granted permissions and boolean , as true if all permissions are granted
     */
    suspend fun requestPermissions(
        activity: ComponentActivity,
        permissionArray: Array<String>
    ): Pair<Array<String>, Boolean> {
        var notGrantedPermission: MutableList<String>? = null
        permissionArray.forEach {
            if (isNotGranted(activity, it)) {
                Log.d(TAG, "requestPermissions: $it is not granted")
                if (notGrantedPermission == null) {
                    notGrantedPermission = mutableListOf()
                    notGrantedPermission!!.add(it)
                } else {
                    notGrantedPermission!!.add(it)
                }
            } else {
                Log.d(TAG, "requestPermissions: $it is already granted")
            }
        }
        val isAllGranted = notGrantedPermission.isNullOrEmpty()
        return if (isAllGranted) {
            Pair(emptyArray(), true)
        } else {
            if (notGrantedPermission!!.size == 1) {
                requestSinglePermission(activity, notGrantedPermission!![0])
            } else {
                requestMultiplePermissions(activity, permissionArray)
            }
        }
    }


    /**
     * Check if the permission is not granted
     * @param fragment: Fragment - Fragment
     * @param permissionArray: Array<String> - Array of permissions
     * @return Pair<Array<String>, Boolean> - Pair of not granted permissions and boolean , as true if all permissions are granted
     */
    suspend fun requestPermissions(
        fragment: Fragment,
        permissionArray: Array<String>
    ): Pair<Array<String>, Boolean> {
        return requestPermissions(fragment.requireActivity(), permissionArray)
    }


    /**
     * requestMultiplePermissions: Request multiple permissions
     * @param activity: ComponentActivity - Activity
     * @param  permissionArray: Array<String> - Array of permissions
     * @return Pair<Array<String>, Boolean> - Pair of not granted permissions and boolean , as true if all permissions are granted
     */
    private  suspend fun requestMultiplePermissions(
        activity: ComponentActivity,
        permissionArray: Array<String>
    ): Pair<Array<String>, Boolean> {
        return suspendCancellableCoroutine { continuation ->
            val permissionLauncher =
                activity.register(
                    "RequestMultiplePermissions",
                    ActivityResultContracts.RequestMultiplePermissions()
                ) { map ->
                    var deniedPermission: MutableList<String>? = null
                    map.forEach { (t, u) ->
                        if (u) {
                            Log.d(TAG, "requestMultiplePermissions: $t is granted")
                        } else {
                            Log.d(TAG, "requestMultiplePermissions: $t is not granted")
                            if (deniedPermission == null) {
                                deniedPermission = mutableListOf()
                            }
                            deniedPermission!!.add(t)
                        }
                    }
                    continuation.resume(
                        Pair(
                            deniedPermission?.toTypedArray() ?: emptyArray(),
                            deniedPermission.isNullOrEmpty()
                        )
                    )
                }
            permissionLauncher.launch(permissionArray)
        }
    }

    /**
     *
     * @param activity: ComponentActivity
     * @param permission: String
     * @return  Pair<Array<String>, Boolean> deniedPermissionArray, isAllPermissionGranted
     */
    private suspend fun requestSinglePermission(
        activity: ComponentActivity,
        permission: String
    ): Pair<Array<String>, Boolean> {
        return suspendCancellableCoroutine { continuation ->
            val permissionLauncher = activity.register(
                "requestSinglePermission",
                ActivityResultContracts.RequestPermission()
            ) {
                if (it) {
                    Log.d(TAG, "$permission is Granted")
                } else {
                    Log.d(TAG, "$permission is Denied")
                }
                continuation.resume(Pair(arrayOf(permission), it))

            }
            permissionLauncher.launch(permission)
        }
    }

    private fun isNotGranted(context: Context, permission: String) = ActivityCompat.checkSelfPermission(
        context, permission
    ) != PackageManager.PERMISSION_GRANTED
}